# albailian.py
from dashscope import MultiModalConversation
import os
import logging
import base64
import requests
from pathlib import Path
import tempfile
import time
import json

# 配置日志系统（DEBUG 用于调试，INFO 用于生产）
logging.basicConfig(
    level=logging.DEBUG,
    format='[%(asctime)s] [%(levelname)s] [%(module)s:%(lineno)d] %(message)s'
)

def upload_to_server(file_path: str, max_retries=3) -> str:
    """
    上传文件到指定服务器并返回远程URL（带重试机制）

    参数:
        file_path (str): 本地文件路径
        max_retries (int): 最大重试次数

    返回:
        str: 服务器返回的远程URL
    """
    upload_url = "http://dev.blueant.pro/base/api.Upload/file_python"

    try:
        logging.debug(f"开始上传文件: {file_path}")
        file_size = os.path.getsize(file_path)
        logging.info(f"文件信息 - 路径: {file_path}, 大小: {file_size} 字节, 类型: {Path(file_path).suffix}")

        # 文件名安全处理
        safe_filename = Path(file_path).name
        with open(file_path, 'rb') as f:
            files = {'file': (safe_filename, f)}

            for attempt in range(max_retries):
                try:
                    logging.debug(f"第{attempt+1}次上传尝试")
                    response = requests.post(
                        upload_url,
                        files=files,
                        timeout=30  # 设置超时时间
                    )
                    break
                except requests.exceptions.RequestException as e:
                    logging.warning(f"上传尝试失败({attempt+1}/{max_retries}): {str(e)}")
                    if attempt == max_retries - 1:
                        raise
                    time.sleep(2 ** attempt)  # 指数退避

        logging.debug(f"上传响应状态码: {response.status_code}")
        logging.debug(f"原始响应内容: {response.text}")

        try:
            result = response.json()
            logging.debug(f"解析后的JSON响应: {json.dumps(result, indent=2)}")
        except json.JSONDecodeError:
            logging.error("无法解析响应JSON")
            raise Exception(f"无效的JSON响应: {response.text}")

        if response.status_code != 200:
            raise Exception(f"HTTP错误: {response.status_code}, 响应: {response.text}")

        if result.get('code') != 1:
            raise Exception(f"上传失败: code={result.get('code')}, info={result.get('info')}")

        remote_url = result['data']['url']
        logging.info(f"上传成功，远程URL: {remote_url}")
        return remote_url

    except Exception as e:
        logging.exception("文件上传过程中发生异常")
        raise

def encode_image(image_path: str) -> str:
    """
    将图片文件转换为 Base64 编码的 Data URI

    参数:
        image_path (str): 图片文件路径

    返回:
        str: Base64编码的Data URI
    """
    logging.debug(f"开始编码图片: {image_path}")

    try:
        with open(image_path, "rb") as image_file:
            encoded_str = base64.b64encode(image_file.read()).decode("utf-8")
            file_size = len(encoded_str)

        file_ext = Path(image_path).suffix.lower()
        mime_type = {
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.png': 'image/png'
        }.get(file_ext, 'application/octet-stream')

        data_uri = f"data:{mime_type};base64,{encoded_str}"
        logging.debug(f"编码完成 - 数据URI长度: {len(data_uri)} 字节, MIME类型: {mime_type}")
        logging.debug(f"Base64前100字符示例: {encoded_str[:100]}...")
        return data_uri

    except Exception as e:
        logging.exception("图片编码过程中发生异常")
        raise

def generate_summary(file_path: str, api_key: str) -> str:
    """
    生成媒体内容摘要（支持视频和图片）

    参数:
        file_path (str): 本地媒体文件路径（支持视频/mp4/avi/mov，图片/jpg/png/jpeg）
        api_key (str): DashScope API密钥

    返回:
        str: 媒体摘要内容（最多50个汉字）
    """
    logging.info("=== 开始执行 generate_summary ===")
    logging.debug(f"输入参数: file_path={file_path}, api_key={'存在' if api_key else '缺失'}")

    try:
        # 文件类型检测
        video_exts = {'.mp4', '.avi', '.mov'}
        image_exts = {'.jpg', '.jpeg', '.png'}

        file_ext = Path(file_path).suffix.lower()
        logging.debug(f"文件扩展名检测结果: {file_ext}")

        # 参数验证
        if not os.path.exists(file_path):
            raise FileNotFoundError(f"文件不存在: {file_path}")

        if file_ext not in video_exts | image_exts:
            logging.warning(f"未知文件类型: {file_ext}，将作为通用文件处理")

        # 文件上传
        logging.info("开始上传文件到远程服务器")
        remote_url = upload_to_server(file_path)
        logging.info(f"文件上传成功，远程URL: {remote_url}")

        # 构建消息内容
        content = []
        if file_ext in video_exts:
            # 视频文件处理
            logging.debug("构建视频处理请求")
            content = [
                {'video': remote_url, "fps": 1},
                {'text': '请用一句话概述视频内容,要求不得多余50个汉字'}
            ]
            messages = [{'role': 'user', 'content': content}]

        elif file_ext in image_exts:
            # 图片文件处理
            logging.debug("开始图片Base64编码")
            encoded_data = encode_image(file_path)
            content = [
                {'image': encoded_data},
                {'text': '请用一句话描述图片内容,要求不得多余50个汉字'}
            ]
            messages = [{'role': 'user', 'content': content}]


        else:
            # 其他类型文件处理
            content = [
                {'file': remote_url},
                {'text': '请用一句话概述文件内容,要求不得多余50个汉字'}
            ]

        #messages = [{'role': 'user', 'content': content}]
        logging.debug(f"构建的消息体: {json.dumps(messages, indent=2)}")

        # API密钥验证
        if not api_key:
            raise ValueError("DASHSCOPE_API_KEY 环境变量未设置")

        # 调用API
        logging.info("开始调用阿里百炼多模态API")
        logging.debug(f"使用的模型: qvq-max (请根据文档确认最新模型名称)")

        response = MultiModalConversation.call(
            # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key="sk-xxx",
            api_key=api_key,
            model="qvq-max",  # 此处以qvq-max为例，可按需更换模型名称。
            messages=messages,
            stream=True,
        )

        # 定义完整思考过程
        reasoning_content = ""
        # 定义完整回复
        answer_content = ""
        # 判断是否结束思考过程并开始回复
        is_answering = False

        print("=" * 20 + "思考过程" + "=" * 20)

        for chunk in response:
            # 如果思考过程与回复皆为空，则忽略
            message = chunk.output.choices[0].message
            reasoning_content_chunk = message.get("reasoning_content", None)
            if (chunk.output.choices[0].message.content == [] and
                    reasoning_content_chunk == ""):
                pass
            else:
                # 如果当前为思考过程
                if reasoning_content_chunk != None and chunk.output.choices[0].message.content == []:
                    print(chunk.output.choices[0].message.reasoning_content, end="")
                    reasoning_content += chunk.output.choices[0].message.reasoning_content
                # 如果当前为回复
                elif chunk.output.choices[0].message.content != []:
                    if not is_answering:
                        print("\n" + "=" * 20 + "完整回复" + "=" * 20)
                        is_answering = True
                    print(chunk.output.choices[0].message.content[0]["text"], end="")
                    answer_content += chunk.output.choices[0].message.content[0]["text"]

        # 如果您需要打印完整思考过程与完整回复，请将以下代码解除注释后运行
        print("=" * 20 + "完整思考过程" + "=" * 20 + "\n")
        print(f"{reasoning_content}")
        print("=" * 20 + "完整回复" + "=" * 20 + "\n")
        print(f"{answer_content}")
        # 响应解析
        #answer_content = ""
        return answer_content
        # 尝试多种解析路径



    except Exception as e:
        logging.critical("生成摘要过程中发生严重错误", exc_info=True)
        raise RuntimeError(f"生成摘要失败: {str(e)}") from e
